#lang scribble/doc


@(require scribble/manual)
@(require rosetta)


@title{Rosetta}
@declare-exporting[Rosetta]


@section{Coords}

Coords represent spatial coordinates and they are used in a variety of situations, for example, to specify the location of geometric shapes.

Coords can be Cartesian, cylindrical, polar or spherical, and there are many operations to manipulate coordinates, such as, addition, subtraction, dot product, cross product, and so on.

There are several alternative names for the functions defined for coordinates, depending on the language you are using.

Example 1: a sphere of radius @racket[10], located at @racket[(1 2 3)], using Cartesian coordinates:
@codeblock{(sphere (xyz 1 2 3) 10)}

Example 2: a sphere of radius @racket[10], located at @racket[(0 1 0)], using polar coordinates:
@codeblock{(sphere (pol 1 pi/2) 10)}

Example 3: using lang @racket[rosetta-racket] and alternative names:
@codeblock{
#lang rosetta-racket

(define (plus-1 c r)
  (sphere (+x c 1) r))
}

Example 4: definition of the @racket[rotate] constructor that rotates a shape based on the begin and end coordinates.
@codeblock{
(define (rotate c1 c2 shape)
  (let ((n (if (< (collinearity-c c1 c2) 0)
               (collinear-cross-c c1)
               (cross-c c1 c2))))
    (rotate (angle-c c1 c2) n shape)))
}


@subsection{Cartesian}

@defproc[(xyz (x number?) (y number?) (z number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates, where
@racket[x] is the @racket[coord?] distance in the X-axis,
@racket[y] is the @racket[coord?] distance in the Y-axis, and
@racket[z] is the @racket[coord?] distance in the Z-axis.
}

@defproc*[(((xy (x number?) (y number?)) coord?)
           ((xy (c coord?) (x number?) (y number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates.
Equivalent to @racket[(xyz x y 0)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[z] value from @racket[c].
Equivalent to @racket[(x y (xyz-z c))].
}

@defproc*[(((yz (y number?) (z number?)) coord?)
           ((yz (c coord?) (y number?) (z number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates.
Equivalent to @racket[(xyz 0 y z)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[x] value from @racket[c].
Equivalent to @racket[(xyz (xyz-x c) y z)].
}
                                                             
@defproc*[(((xz (x number?) (z number?)) coord?)
           ((xz (c coord?) (x number?) (z number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates.
Equivalent to @racket[(xyz x 0 z)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[y] value from @racket[c]
Equivalent to @racket[(xyz x (xyz-y c) z)].
}

@defproc*[(((x (x number?)) coord?)
           ((x (c coord?) (x number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates.
Equivalent to @racket[(xyz x 0 0)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[y] and @racket[z] values from @racket[c].
Equivalent to @racket[(xyz x (xyz-y c) (xyz-z c))].
}
                                                
@defproc*[(((y (y number?)) coord?)
           ((y (c coord?) (y number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates
Equivalent to @racket[(xyz 0 y 0)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[x] and @racket[z] values from @racket[c]
Equivalent to @racket[(xyz (xyz-x c) y (xyz-z c))].
}
                                                
@defproc*[(((z (z number?)) coord?)
           ((z (c coord?) (z number?)) coord?))]{
The first version creates a @racket[coord?] using Cartesian coordinates
Equivalent to @racket[(xyz 0 0 z)].

The second version creates a @racket[coord?] using Cartesian coordinates with @racket[x] and @racket[y] values from @racket[c]
Equivalent to @racket[(xyz (xyz-x c) (xyz-y c) z)].
}
                                                
@defproc[(xyz-x (c coord?)) number?]{
Returns the Cartesian @racket[x] value of @racket[c].
}

@defproc[(xyz-y (c coord?)) number?]{
Returns the Cartesian @racket[y] value of @racket[c].
}

@defproc[(xyz-z (c coord?)) number?]{
Returns the Cartesian @racket[z] value of @racket[c].
}

@defproc[(xyz-r (c coord?)) number?]{
Returns the length of @racket[c].
}


@subsection{Cylindrical}

@defproc[(cyl (rho distance?) (phi number?) (z number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates, where
@racket[rho] is the distance of the @racket[coord?] projection in the XY-plane,
@racket[phi] is the angle in the XY-plane with the X-axis, and
@racket[z] is equivalent to the Cartesian @racket[z].
}

@defproc[(cyl-rho (c coord?)) distance?]{
Returns the cylindrical @racket[rho] value of @racket[c].
                        
In lang @racket[rosetta-racket], use @racket[cyl-ρ] instead.
}

@defproc[(cyl-phi (c coord?)) number?]{
Returns the cylindrical @racket[phi] value of @racket[c].
                        
In lang @racket[rosetta-racket], use @racket[cyl-φ] instead.
}

@defproc[(cyl-z (c coord?)) number?]{
Returns the cylindrical @racket[z] value of @racket[c].
}


@subsection{Polar}

Polar coordinates are a particular case of cylindrical coordinates,
where the value of @racket[z] is @racket[0].

@defproc[(pol (rho distance?) (phi number?)) coord?]{
Creates a @racket[coord?] using polar coordinates.
Equivalent to @racket[(cyl rho phi 0)].
}

@defproc[(pol-rho (c coord?)) distance?]{
Returns the polar @racket[rho] value of @racket[c].
Equivalent to @racket[cyl-rho] but the @racket[z] value of @racket[c] is ignored.

In lang @racket[rosetta-racket], use @racket[pol-ρ] instead.
}

@defproc[(pol-phi (c coord?)) number?]{
Returns the polar @racket[phi] value of @racket[c].
Equivalent to @racket[cyl-phi] but the @racket[z] value of @racket[c] is ignored.

In lang @racket[rosetta-racket], use @racket[pol-φ] instead.
}


@subsection{Spherical}

@defproc[(sph (r distance?) (phi number?) (th number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates, where
@racket[r] is the distance of the @racket[coord?],
@racket[phi] is the angle in the XY-plane with the X-axis, and
@racket[th] is the angle in the vertical plane defined by @racket[phi] with the Z-axis.
}

@defproc[(sph-r (c coord?)) distance?]{
Returns the spherical @racket[r] value of @racket[c].
Equivalent to @racket[xyz-r].
}

@defproc[(sph-phi (c coord?)) number?]{
Returns the spherical @racket[phi] value of @racket[c].
                      
In lang @racket[rosetta-racket], use @racket[sph-φ] instead.
}

@defproc[(sph-th (c coord?)) number?]{
Returns the spherical @racket[th] value of @racket[c].
                      
In lang @racket[rosetta-racket], use @racket[sph-θ] instead.
}


@subsection{Constants}

@defidform[u0]{
A convenience name for the origin, e.g., @racket[(xyz 0 0 0)].
}


@defidform[ux]{
A convenience name for the X-axis unit vector, e.g., @racket[(xyz 1 0 0)].
}

@defidform[uy]{
A convenience name for the Y-axis unit vector, e.g., @racket[(xyz 0 1 0)].
}

@defidform[uz]{
A convenience name for the Z-axis unit vector, e.g., @racket[(xyz 0 0 1)].
}


@defidform[uxy]{
A convenience name for the addition of @racket[ux] and @racket[uy], e.g., @racket[(xyz 1 1 0)].
}

@defidform[uyz]{
A convenience name for the addition of @racket[uy] and @racket[uz], e.g., @racket[(xyz 0 1 1)].
}

@defidform[uxz]{
A convenience name for the addition of @racket[ux] and @racket[uz], e.g., @racket[(xyz 1 0 1)].
}

@defidform[uxyz]{
A convenience name for the addition of @racket[ux], @racket[uy] and @racket[uz], e.g., @racket[(xyz 1 1 1)].
}


@subsection{Predicates}

@defproc[(is-coord (c any/c)) boolean?]{
Tests if @racket[c] is a @racket[coord?].
         
In lang @racket[rosetta-racket], use @racket[coord?] instead.
}

@defproc[(u0? (c any/c)) boolean?]{
Tests if @racket[c] is a @racket[coord?] and if it is the origin.
         
In lang @racket[rosetta-racket], use @racket[u0?] instead.
}


@subsection{Operations}

@defproc*[(((eq-c (c1 coord?) (c2 coord?)) boolean?)
           ((eq-c (c1 coord?) (c2 coord?) (threshold-d (not/c negative?))) boolean?))]{
The first version tests if @racket[c1] and @racket[c2] are @racket[equal?].

The second version tests if @racket[c1] and @racket[c2] are @racket[equal?] given the @racket[threshold-d].
If @racket[(= threshold-d 0)] then the second version is equivalent to the first.

In lang @racket[rosetta-racket], use @racket[=c] instead.
}

@defproc*[(((add-c (c1 coord?) (c2 coord?)) coord?)
           ((add-c (c1 coord?) (c2 coord?) ...) coord?))]{
The first version creates a @racket[coord?] that results from adding @racket[c1] and @racket[c2].

The second version creates a @racket[coord?] that results from adding @racket[c1], @racket[c2] and @racket[...].
If @racket[(empty? ...)] then the second version is equivalent to the first.

In lang @racket[rosetta-racket], use @racket[+c] instead.
}

@defproc*[(((sub-c (c1 coord?) (c2 coord?)) coord?)
           ((sub-c (c1 coord?) (c2 coord?) ...) coord?))]{
The first version creates a @racket[coord?] that results from subtracting @racket[c1] and @racket[c2].

The second version creates a @racket[coord?] that results from subtracting @racket[c1], @racket[c2] and @racket[...].
If @racket[(empty? ...)] then the second version is equivalent to the first.

In lang @racket[rosetta-racket], use @racket[-c] instead.
}

@defproc[(dot-c (c1 coord?) (c2 coord?)) number?]{
Returns the dot product of @racket[c1] and @racket[c2].

In lang @racket[rosetta-racket], use @racket[.c] instead.
}

@defproc[(cross-c (c1 coord?) (c2 coord?)) coord?]{
Creates a @racket[coord?] that results from the cross product of @racket[c1] and @racket[c2].
In other words, it creates a @racket[coord?] that is perpendicular to both @racket[c1] and @racket[c2].

In lang @racket[rosetta-racket], use @racket[xc] instead.
}

@defproc[(collinear-cross-c (c coord?)) coord?]{
Creates a @racket[coord?] that is perpendicular @racket[c].
          
In lang @racket[rosetta-racket], use @racket[collinear-xc] instead.
}

@defproc*[(((angle-c (c1 coord?) (c2 coord?)) number?)
           ((angle-c (c1 coord?) (c2 coord?) (normal coord?)) number?))]{
The first version returns the shortest angle between @racket[c1] and @racket[c2].

The second version returns the angle between @racket[c1] and @racket[c2], where
@racket[normal] defines the direction of the angle,
thus allowing angles greater than @racket[pi] as result.

In lang @racket[rosetta-racket], use @racket[</c] instead.
}

@defproc[(collinearity-c (c1 coord?) (c2 coord?)) number?]{
Returns the collinearity factor @racket[r] between @racket[c1] and @racket[c2], such that
@racket[(=c c1 (*c c2 r))].
          
In lang @racket[rosetta-racket], use @racket[//c] instead.
}

@defproc*[(((mult-c (c coord?) (r number?)) coord?)
           ((mult-c (r number?) (c coord?)) coord?))]{
Both versions create a @racket[coord?] that results from the scalar multiplication of @racket[c] by @racket[r].

In lang @racket[rosetta-racket], use @racket[*c] instead.
}


@defproc[(distance (c1 coord?) (c2 coord?)) number?]{
Returns the distance between @racket[c1] and @racket[c2].
}

@defproc[(midcoord (c1 coord?) (c2 coord?)) number?]{
Creates a @racket[coord?] that is halfway between @racket[c1] and @racket[c2].
}

@defproc[(norm (c coord?)) number?]{
Creates a @racket[coord?] @racket[d], such that @racket[c] and @racket[n] are collinear, and @racket[(= (xyz-r d) 1)].
}

@defproc[(symmetric (c coord?)) coord?]{
Creates a @racket[coord?] @racket[d], such that @racket[c] and @racket[n] are collinear, and @racket[(= (collinearity-c c d) -1)].
}


@defproc[(add-x-c (c coord?) (r number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that @racket[y] and @racket[z] values are taken from @racket[c],
and the @racket[x] value results from the addition of the @racket[x] value of @racket[c] with @racket[r].
Equivalent to @racket[(x c (+ (xyz-x c) r))].

In lang @racket[rosetta-racket], use @racket[+x] instead.
}

@defproc[(add-y-c (c coord?) (r number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that @racket[x] and @racket[z] values are taken from @racket[c],
and the @racket[y] value results from the addition of the @racket[y] value of @racket[c] with @racket[r].
Equivalent to @racket[(y c (+ (xyz-y c) r))].

In lang @racket[rosetta-racket], use @racket[+y] instead.
}

@defproc[(add-z-c (c coord?) (r number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that @racket[x] and @racket[y] values are taken from @racket[c],
and the @racket[z] value results from the addition of the @racket[z] value @racket[c] with @racket[r].
Equivalent to @racket[(z c (+ (xyz-z c) r))].

In lang @racket[rosetta-racket], use @racket[+z] instead.
}

@defproc[(add-xy-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that the @racket[z] value is taken from @racket[c],
and both @racket[x] and @racket[y] values result from the addition of @racket[x] and @racket[y] values of @racket[c] with parameters @racket[x] and @racket[y], respectively.

Equivalent to @racket[(xy c (+ (xyz-x c) x) (+ (xyz-y c) y))].

In lang @racket[rosetta-racket], use @racket[+xy] instead.
}

@defproc[(add-yz-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that the @racket[x] value is taken from @racket[c],
and both @racket[y] and @racket[z] values result from the addition of @racket[y] and @racket[z] values of @racket[c] with parameters @racket[x] and @racket[y], respectively.

Equivalent to @racket[(yz c (+ (xyz-y c) x) (+ (xyz-z c) y))].

In lang @racket[rosetta-racket], use @racket[+yz] instead.
}

@defproc[(add-xz-c (c coord?) (x number?) (y number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that the @racket[y] value is taken from @racket[c],
and both @racket[x] and @racket[z] values result from the addition of @racket[x] and @racket[z] values of @racket[c] with parameters @racket[x] and @racket[y], respectively.

Equivalent to @racket[(xz c (+ (xyz-x c) x) (+ (xyz-z c) y))].

In lang @racket[rosetta-racket], use @racket[+xz] instead.
}

@defproc[(add-xyz-c (c coord?) (x number?) (y number?) (z number?)) coord?]{
Creates a @racket[coord?] using Cartesian coordinates,
such that @racket[x], @racket[y] and @racket[z] values result from the addition of @racket[x], @racket[y] and @racket[z] values of @racket[c]
with parameters @racket[x], @racket[y] and @racket[z], respectively.

Equivalent to @racket[(xyz c (+ (xyz-x c) x) (+ (xyz-y c) y) (+ (xyz-z c) z))].

In lang @racket[rosetta-racket], use @racket[+xyz] instead.
}

@defproc[(add-cyl-c (c coord?) (rho number?) (phi number?) (z number?)) coord?]{
Creates a @racket[coord?] using cylindrical coordinates,
such that @racket[rho], @racket[phi] and @racket[z] values result from the addition of @racket[rho], @racket[phi] and @racket[z] values of @racket[c]
with parameters @racket[rho], @racket[phi] and @racket[z], respectively.

Equivalent to @racket[(cyl c (+ (cyl-rho c) rho) (+ (cyl-phi c) phi) (+ (cyl-z c) z))].

In lang @racket[rosetta-racket], use @racket[+cyl] instead.
}

@defproc[(add-pol-c (c coord?) (rho number?) (phi number?)) coord?]{
Creates a @racket[coord?] using polar coordinates,
such that @racket[rho] and @racket[phi] values result from the addition of @racket[rho] and @racket[phi] values of @racket[c]
with parameters @racket[rho] and @racket[phi], respectively.

Equivalent to
@itemlist{@item{@racket[(pol c (+ (pol-rho c) rho) (+ (pol-phi c) phi))]}@item{@racket[(+cyl c (+ (pol-rho c) rho) (+ (pol-phi c) phi) 0)]}}

In lang @racket[rosetta-racket], use @racket[+pol] instead.
}

@defproc[(add-sph-c (c coord?) (r number?) (phi number?) (th number?)) coord?]{
Creates a @racket[coord?] using spherical coordinates,
such that @racket[r], @racket[phi] and @racket[th] values result from the addition of @racket[rho], @racket[phi] and @racket[th] values of @racket[c]
with parameters @racket[rho], @racket[phi] and @racket[th], respectively.

Equivalent to @racket[(sph c (+ (sph-r c) rho) (+ (sph-phi c) phi) (+ (sph-th c) th))].

In lang @racket[rosetta-racket], use @racket[+sph] instead.
}

@defproc[(list-of-coord (c coord?)) (listof number?)]{
Creates a @racket[list?] whose elements are the Cartesian values of @racket[c].

Equivalent to @racket[(list (xyz-x c) (xyz-y c) (xyz-z c))].

In lang @racket[rosetta-racket], use @racket[list<-coord] instead.
}

@defproc[(vector-of-coord (c coord?)) (vectorof number?)]{
Creates a @racket[vector?] whose elements are the Cartesian values of @racket[c].

Equivalent to @racket[(vector (xyz-x c) (xyz-y c) (xyz-z c))].

In lang @racket[rosetta-racket], use @racket[vector<-coord] instead.
}

@defproc[(coord-of-vector (v (vectorof number?))) (vectorof number?)]{
Creates a @racket[coord?] using Cartesian coordinates,
where @racket[x], @racket[y] and @racket[z] values are the elements of @racket[v].

Equivalent to @racket[(apply xyz (vector->list v))].

In lang @racket[rosetta-racket], use @racket[coord<-vector] instead.
}